package com.py.framework.service.impl;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.py.framework.common.Constants;
import com.py.framework.core.exception.ServiceException;
import com.py.framework.core.log.ExceptionLogger;
import com.py.framework.core.redis.bis.JedisBisManage;
import com.py.framework.core.utils.DateUtils;
import com.py.framework.core.utils.SerializingUtil;
import com.py.framework.dao.AreaDao;
import com.py.framework.entity.AreaEntity;
import com.py.framework.entity.OfficeEntity;
import com.py.framework.service.AreaService;
import com.py.framework.service.OfficeService;

import redis.clients.jedis.Jedis;

/**
 * 区域管理Service实现
 * @author Leegern
 * @date   2018年4月20日
 */
@Service
public class AreaServiceImpl implements AreaService {
	
	@Autowired
	private AreaDao areaDao;
	@Autowired
	private OfficeService officeService;
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#addAreaInfo(com.py.framework.entity.AreaEntity)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int addAreaInfo(AreaEntity entity) {
		this.clearAreasCache();
		if (entity.getParentId() > Constants.NUMBER_ZERO) {
			AreaEntity area = this.findOneArea(entity.getParentId());
			if (null != area && StringUtils.isNotBlank(area.getAllParentId())) {
				entity.setAllParentId(area.getAllParentId() + "," + entity.getParentId());
			} else {
				entity.setAllParentId(String.valueOf(entity.getParentId()));
			}
		}
		entity.setCreateTime(new Timestamp(System.currentTimeMillis()));
		entity.setUpdateTime(new Timestamp(System.currentTimeMillis()));
		entity.setDelFlag(Constants.NUMBER_ONE);
		return areaDao.addAreaInfo(entity);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#queryAreasForPage(java.util.Map)
	 */
	@Override
	public List<AreaEntity> queryAreasForPage(Map<String, Object> params) {
		if (! CollectionUtils.isEmpty(params)) {
			return areaDao.queryAreasForPage(params);
		}
		return null;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#getAllAreas()
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<AreaEntity> getAllAreas() {
		List<AreaEntity> areas = null;
		Jedis jedis = null;
		byte[] datas = null;
		try {
			jedis = JedisBisManage.getJedis();
			datas = jedis.get(SerializingUtil.serialize(Constants.ALL_AREA_KEY));
			if (null == datas || datas.length == 0) {
				areas = areaDao.getAreasByParentId(null);
				if (! CollectionUtils.isEmpty(areas)) {
					jedis.set(SerializingUtil.serialize(Constants.ALL_AREA_KEY), SerializingUtil.serialize(areas));
				} 
			} else {
				areas = (List<AreaEntity>) SerializingUtil.deserialize(datas);
			}
		} catch (Exception e) {
			ExceptionLogger.error(e);
		} finally {
			if (null != jedis) JedisBisManage.returnResource(jedis);
		}
		return areas;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#getRootArea()
	 */
	@Override
	public List<AreaEntity> getRootArea() {
		return areaDao.getRootArea();
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#getSecondAreas(long)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<AreaEntity> getSecondAreas(long rootId) {
		List<AreaEntity> areas = null;
		Jedis jedis = null;
		byte[] datas = null;
		try {
			jedis = JedisBisManage.getJedis();
			datas = jedis.get(SerializingUtil.serialize(Constants.SEC_AREA_KEY));
			if (null == datas || datas.length == 0) {
				areas = areaDao.getSecondAreas(rootId);
				if (! CollectionUtils.isEmpty(areas)) {
					jedis.set(SerializingUtil.serialize(Constants.SEC_AREA_KEY), SerializingUtil.serialize(areas));
				} 
			} else {
				areas = (List<AreaEntity>) SerializingUtil.deserialize(datas);
			}
		} catch (Exception e) {
			ExceptionLogger.error(e);
		} finally {
			if (null != jedis) JedisBisManage.returnResource(jedis);
		}
		return areas;
	}
	

	@Override
	public List<AreaEntity> getAreasByIds(List<Long> ids) {
		if (! CollectionUtils.isEmpty(ids)) {
			return areaDao.getAreasByIds(ids);
		}
		return null;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#getAreasByParentId(java.lang.String)
	 */
	@Override
	public List<AreaEntity> getAreasByParentId(String parentId) {
		if (StringUtils.isNotBlank(parentId)) {
			return areaDao.getAreasByParentId(parentId);
		}
		return null;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#findOneArea(long)
	 */
	@Override
	public AreaEntity findOneArea(long id) {
		if (id > Constants.NUMBER_ZERO) {
			return areaDao.findOneArea(id);
		}
		return null;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#updateArea(com.py.framework.entity.AreaEntity)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int updateArea(AreaEntity entity) {
		this.clearAreasCache();
		entity.setUpdateTime(new Timestamp(System.currentTimeMillis()));
		return areaDao.updateArea(entity);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#batchDelArea(java.util.List)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int batchDelArea(List<Long> ids) {
		int result = 0;
		if (! CollectionUtils.isEmpty(ids)) {
			List<AreaEntity> datas = null;
			List<OfficeEntity> offices = null;
			for (Long id : ids) {
				datas = areaDao.getSubAreasById(String.valueOf(id));
				if (! CollectionUtils.isEmpty(datas)) {
					throw new ServiceException("存在子节点，删除失败！");
				}
				offices = officeService.getOfficesByAreaId(id);
				if (! CollectionUtils.isEmpty(offices)) {
					throw new ServiceException("存在部门，删除失败！");
				}
			}
			Map<String, Object> params = new HashMap<>();
			params.put("updateTime", new Timestamp(DateUtils.getCurrentDateTime().getTime()));
			params.put("ids",        ids);
			result = areaDao.batchDelArea(params);
			this.clearAreasCache();
		}
		return result;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#getAreasByCode(long, java.lang.String)
	 */
	@Override
	public List<AreaEntity> getAreasByCode(long areaId, String areaCode) {
		return areaDao.getAreasByCode(areaId, areaCode);
	}
		
	/*
	 * (non-Javadoc)
	 * @see com.py.framework.service.AreaService#getAreasByPid(long)
	 */
	@Override
	public List<AreaEntity> getAreasByPid(long parentId) {
		return areaDao.getAreasByPid(parentId);
	}
	
	/**
	 * 清空区域缓存
	 */
	private void clearAreasCache() {
		Jedis jedis = null;
		try {
			jedis = JedisBisManage.getJedis();
			jedis.del(SerializingUtil.serialize(Constants.ALL_AREA_KEY));
			jedis.del(SerializingUtil.serialize(Constants.SEC_AREA_KEY));
		} catch (Exception e) {
			ExceptionLogger.error(e);
		} finally {
			if (null != jedis) JedisBisManage.returnResource(jedis);
		}
	}
}